@tool
class_name Detector_Obstacle
extends Detector

#region 属性
@export var radius:float = 30
@export var resolution_radio:int = 12
@export var target_type:GameEnum.TargetDetectorTargetType
@export_flags_2d_physics var obstacle_layer_mask:int
var obstacle_closest_point:Array[Vector2] = []
var ray_cast_2ds:Array[RayCast2D] = []
#endregion
#region 字段
#endregion
#region 信号
#endregion

#region 基类方法
func init(entity:Entity,args:Dictionary = {}) -> bool:
	if super.init(entity):
		for i in range(resolution_radio):
			var angle = 360.0 / resolution_radio
			var ray_cast_2d = RayCast2D.new()
			ray_cast_2d.target_position = Vector2(radius,0)
			ray_cast_2d.rotate(deg_to_rad(angle) * i)
			ray_cast_2d.enabled = false
			ray_cast_2ds.append(ray_cast_2d)
			add_child(ray_cast_2d)
		return true
	return false
func set_enable(enable:bool):
	if enable and not self.enable:
		for ray_cast_2d in ray_cast_2ds:
			ray_cast_2d.enabled = enable
	elif not enable and self.enable:
		for ray_cast_2d in ray_cast_2ds:
			ray_cast_2d.enabled = enable
func update(delta:float) -> bool:
	if super(delta):
		for ray_cast_2d in ray_cast_2ds:
			ray_cast_2d.target_position = Vector2(radius,0)
			#ray_cast_2d.collision_mask = entity.entity_data.get_obstacle_layer_mask()
			ray_cast_2d.collision_mask = obstacle_layer_mask
		obstacle_closest_point.clear()
		for ray_cast_2d in ray_cast_2ds:
			ray_cast_2d.force_raycast_update()
			if ray_cast_2d.is_colliding():
				obstacle_closest_point.append(ray_cast_2d.get_collision_point())
		return true
	return false
func destroy():
	super()
#endregion
#region 公共方法
func get_points(pos:Vector2,radius:float = 0,filter_func:Callable = Callable(),count:int = -1) -> Array:
	if radius <= 0:
		return get_normal_points(pos,filter_func,count)
	var new_obstacle_closest_point = []
	for ray_cast_2d in ray_cast_2ds:
		ray_cast_2d.target_position = Vector2(radius,0)
		ray_cast_2d.force_raycast_update()
		if ray_cast_2d.is_colliding():
			new_obstacle_closest_point.append(ray_cast_2d.get_collision_point())
	var obstacle_closest_point_copy = new_obstacle_closest_point.duplicate()
	if filter_func and filter_func.is_valid():
		obstacle_closest_point_copy = obstacle_closest_point_copy.filter(filter_func)
	obstacle_closest_point_copy.sort_custom(func (a:Vector2,b:Vector2):return (a-pos).length() < (b-pos).length())
	return obstacle_closest_point_copy.slice(0,count if count >= 0 else obstacle_closest_point_copy.size())
func get_normal_points(pos:Vector2,filter_func:Callable = Callable(),count:int = -1) -> Array:
	var obstacle_closest_point_copy = obstacle_closest_point.duplicate()
	if filter_func and filter_func.is_valid():
		obstacle_closest_point_copy = obstacle_closest_point_copy.filter(filter_func)
	obstacle_closest_point_copy.sort_custom(func (a:Vector2,b:Vector2):return (a-pos).length() < (b-pos).length())
	return obstacle_closest_point_copy.slice(0,count if count >= 0 else obstacle_closest_point_copy.size())
#endregion
#region 私有方法
#endregion
#region 生命周期函数
func _init() -> void:
	detector_type = GameEnum.DetectorType.Obstacle
func _draw() -> void:
	if not is_debug:
		return
	if GameManager.game_mode != GameEnum.GameMode.Dev:
		return
	draw_circle(position,radius,Color.RED,false)
#endregion
